package config

import (
	"context"
	"net/http"

	"github.com/glennliao/apijson-go/model"
	"github.com/samber/lo"
)

type C查询配置 struct {
	F访问控制   *F访问控制
	H函数集合   *H函数集合
	Z最大树深度  int
	Z最大树宽度  int
	M默认角色函数 M默认角色函数
}

func (配置 *C查询配置) W无需验证() bool {
	return 配置.F访问控制.J禁用验证
}

func (配置 *C查询配置) H获取默认角色函数() M默认角色函数 {
	return 配置.M默认角色函数
}

func (配置 *C查询配置) H获取访问配置(键 string, 无需验证 bool) (*F访问配置结构, error) {
	return 配置.F访问控制.H获取访问配置(键, 无需验证)
}

func (配置 *C查询配置) H获取函数(名称 string) *H函数定义 {
	return 配置.H函数集合.H函数映射[名称]
}

func (配置 *C查询配置) T调用函数(ctx context.Context, 名称 string, 参数 model.Map) (结果 any, 错误 error) {
	return 配置.H函数集合.T调用函数(ctx, 名称, 参数)
}

func (配置 *C查询配置) H获取最大树深度() int {
	return 配置.Z最大树深度
}

func (配置 *C查询配置) H获取最大树宽度() int {
	return 配置.Z最大树宽度
}

type Z执行器配置 struct {
	W无需验证    bool
	F访问配置    *F访问配置结构
	Q请求方法    string
	J角色      string
	S数据库元信息  *S数据库元信息
	S数据库字段风格 Z字段风格转换函数
	JSON字段风格 Z字段风格转换函数
}

func X新建执行器配置(访问配置 *F访问配置结构, 请求方法 string, 无需验证 bool) *Z执行器配置 {
	return &Z执行器配置{
		F访问配置: 访问配置,
		Q请求方法: 请求方法,
		W无需验证: 无需验证,
	}
}

func (配置 *Z执行器配置) S设置角色(角色 string) {
	配置.J角色 = 角色
}

func (配置 *Z执行器配置) H获取表名() string {
	return 配置.F访问配置.M名称
}

func (配置 *Z执行器配置) H获取表字段列表() []string {
	return 配置.S数据库元信息.H获取表字段列表(配置.F访问配置.M名称)
}

func (配置 *Z执行器配置) G根据角色获取字段获取配置() *FieldsGetValue {
	if 值, 存在 := 配置.F访问配置.Z字段获取配置[配置.J角色]; 存在 {
		return 值
	}

	return 配置.F访问配置.Z字段获取配置["default"]
}

func (配置 *Z执行器配置) G根据角色获取输出字段列表() []string {
	var 字段映射 map[string]string

	if 值, 存在 := 配置.F访问配置.Z字段获取配置[配置.J角色]; 存在 {
		字段映射 = 值.Out
	} else {
		字段映射 = 配置.F访问配置.Z字段获取配置["default"].Out
	}
	return lo.Keys(字段映射)
}

func (配置 *Z执行器配置) G根据角色获取输入字段映射() map[string][]string {
	var 输入字段映射 map[string][]string

	if 值, 存在 := 配置.F访问配置.Z字段获取配置[配置.J角色]; 存在 {
		输入字段映射 = 值.In
	} else {
		输入字段映射 = 配置.F访问配置.Z字段获取配置["default"].In
	}

	return 输入字段映射
}

func (配置 *Z执行器配置) H获取访问角色列表() []string {
	switch 配置.Q请求方法 {
	case http.MethodGet:
		return 配置.F访问配置.H获取权限
	case http.MethodHead:
		return 配置.F访问配置.T头部权限
	case http.MethodPost:
		return 配置.F访问配置.T提交权限
	case http.MethodPut:
		return 配置.F访问配置.G更新权限
	case http.MethodDelete:
		return 配置.F访问配置.S删除权限
	}
	return []string{}
}

func (配置 *Z执行器配置) H获取执行器名称() string {
	return 配置.F访问配置.Z执行器
}
